home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / octa209s.zip / octave-2.09 / libs / info / gnuview.c < prev    next >
C/C++ Source or Header  |  1997-08-16  |  14KB  |  451 lines

  1. /* gnuview.c -- This program interprets the commandline arguments like
  2.    info does and starts OS/2 view.exe. */
  3.  
  4. /* Copyright (C) 1993 Free Software Foundation, Inc.
  5.  
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2, or (at your option)
  9.    any later version.
  10.  
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19.  
  20.    Written by Klaus Gebhardt. */
  21.  
  22. #include "getopt.h"
  23.  
  24. #include <stdio.h>
  25. #include <ctype.h>
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include <string.h>
  29. #include <process.h>
  30. #include <ctype.h>
  31.  
  32. /* Defines that are passed along with the pathname to gnuview_add_path (). */
  33. #define INFOPATH_PREPEND               0
  34. #define INFOPATH_APPEND                1
  35. #define INFOPATH_APPEND_WITHOUT_COLON  2
  36. #define INFOPATH_PREPEND_WITHOUT_COLON 3
  37.  
  38. #define COLONCHR ';'
  39. #define COLONSTR ";"
  40. #define PATHSEPCHR '\\'
  41. #define PATHSEPSTR "\\"
  42.  
  43. /* Add POINTER to the list of pointers found in ARRAY.  SLOTS is the number
  44.    of slots that have already been allocated.  INDEX is the index into the
  45.    array where POINTER should be added.  GROW is the number of slots to grow
  46.    ARRAY by, in the case that it needs growing.  TYPE is a cast of the type
  47.    of object stored in ARRAY (e.g., NODE_ENTRY *. */
  48. #define add_pointer_to_array(pointer, idx, array, slots, grow, type) \
  49.   do { \
  50.     if (idx + 2 >= slots) \
  51.       array = (type *)(xrealloc (array, (slots += grow) * sizeof (type))); \
  52.     array[idx++] = (type)pointer; \
  53.     array[idx] = (type)NULL; \
  54.   } while (0)
  55.  
  56. #define maybe_free(x) do { if (x) free (x); } while (0)
  57.  
  58. /* The version numbers of this version of GnuView. */
  59. int gnuview_major_version = 1;
  60. int gnuview_minor_version = 0;
  61. int gnuview_patch_level = 0;
  62.  
  63. /* Non-zero means search all indices for APROPOS_SEARCH_STRING. */
  64. static int apropos_p = 0;
  65.  
  66. /* Variable containing the string to search for when apropos_p is non-zero. */
  67. static char *apropos_search_string = (char *)NULL;
  68.  
  69. /* Non-zero means search all indices for INDEX_SEARCH_STRING.  Unlike
  70.    apropos, this puts the user at the node, running GnuView. */
  71. static int index_search_p = 0;
  72.  
  73. /* Variable containing the string to search for when index_search_p is
  74.    non-zero. */
  75. static char *index_search_string = (char *)NULL;
  76.  
  77. /* Non-zero means print version GnuView only. */
  78. static int print_version_p = 0;
  79.  
  80. /* Non-zero means print a short description of the options. */
  81. static int print_help_p = 0;
  82.  
  83. /* Array of the names of nodes that the user specified with "--node" on the
  84.    command line. */
  85. static char **user_nodenames = (char **)NULL;
  86. static int user_nodenames_index = 0;
  87. static int user_nodenames_slots = 0;
  88.  
  89. /* String specifying the first file to load.  This string can only be set
  90.    by the user specifying "--file" on the command line. */
  91. static char *user_filename = (char *)NULL;
  92.  
  93. /* String specifying the name of the file to dump nodes to.  This value is
  94.    filled if the user speficies "--output" on the command line. */
  95. static char *user_output_filename = (char *)NULL;
  96.  
  97. /* Non-zero indicates that when "--output" is specified, all of the menu
  98.    items of the specified nodes (and their subnodes as well) should be
  99.    dumped in the order encountered.  This basically can print a book. */
  100. int dump_subnodes = 0;
  101.  
  102. /* Structure describing the options that GnuView accepts.  We pass this
  103.    structure to getopt_long ().  If you add or otherwise change this
  104.    structure, you must also change the string which follows it. */
  105. #define APROPOS_OPTION 1
  106. #define DRIBBLE_OPTION 2
  107. #define RESTORE_OPTION 3
  108. #define IDXSRCH_OPTION 4
  109. static struct option long_options[] = {
  110.   { "apropos", 1, 0, APROPOS_OPTION },
  111.   { "directory", 1, 0, 'd' },
  112.   { "node", 1, 0, 'n' },
  113.   { "file", 1, 0, 'f' },
  114.   { "subnodes", 0, &dump_subnodes, 1 },
  115.   { "output", 1, 0, 'o' },
  116.   { "help", 0, &print_help_p, 1 },
  117.   { "version", 0, &print_version_p, 1 },
  118.   { "dribble", 1, 0, DRIBBLE_OPTION },
  119.   { "restore", 1, 0, RESTORE_OPTION },
  120.   { "index-search", 1, 0, IDXSRCH_OPTION },
  121.   {NULL, 0, NULL, 0}
  122. };
  123.  
  124. /* String describing the shorthand versions of the long options found above. */
  125. static char *short_options = "d:n:f:o:sh?";
  126.  
  127. /* Some "forward" declarations. */
  128. static void usage ();
  129. static void gnuview_short_help ();
  130. static void remember_gnuview_program_name ();
  131. static char *gnuview_version_string ();
  132.  
  133. /* The path on which we look for info files.  You can initialize this
  134.    from the environment variable BOOKSHELF if there is one, or you can
  135.    call gnuview_add_path () to add paths to the beginning or end of it. */
  136. char *gnuviewpath = (char *)NULL;
  137. static int gnuviewpath_size = 0;
  138.  
  139. static void gnuview_add_path (char *, int);
  140.  
  141. static void os2_path_sep (char *);
  142. static char *gnuview_filename_non_directory (char *);
  143.  
  144. char *program_name = (char *)NULL;
  145.  
  146.  
  147. /* **************************************************************** */
  148. /*                                    */
  149. /*          Main Entry Point to the GnuView Program        */
  150. /*                                    */
  151. /* **************************************************************** */
  152.  
  153. int main (int argc, char **argv)
  154. {
  155.   int getopt_long_index;    /* Index returned by getopt_long (). */
  156.  
  157.   remember_gnuview_program_name (argv[0]);
  158.  
  159.   setvbuf(stdout, NULL, _IOFBF, BUFSIZ);
  160.  
  161.   while (1)
  162.     {
  163.       int option_character;
  164.  
  165.       option_character = getopt_long
  166.     (argc, argv, short_options, long_options, &getopt_long_index);
  167.  
  168.       /* getopt_long () returns EOF when there are no more long options. */
  169.       if (option_character == EOF) break;
  170.  
  171.       /* If this is a long option, then get the short version of it. */
  172.       if (option_character == 0 && long_options[getopt_long_index].flag == 0)
  173.     option_character = long_options[getopt_long_index].val;
  174.  
  175.       /* Case on the option that we have received. */
  176.       switch (option_character)
  177.     {
  178.     case 0:
  179.       break;
  180.  
  181.       /* User wants to add a directory. */
  182.     case 'd':
  183.       gnuview_add_path (optarg, INFOPATH_PREPEND);
  184.       break;
  185.  
  186.       /* User is specifying a particular node. */
  187.     case 'n':
  188.       add_pointer_to_array (optarg, user_nodenames_index, user_nodenames,
  189.                 user_nodenames_slots, 10, char *);
  190.       break;
  191.  
  192.       /* User is specifying a particular INF file. */
  193.     case 'f':
  194.       if (user_filename) free (user_filename);
  195.       os2_path_sep (user_filename = strdup (optarg));
  196.       break;
  197.  
  198.       /* User is requesting help. */
  199.     case 'h':
  200.       print_help_p = 1;
  201.       break;
  202.  
  203.       /* User is specifying the name of a file to output to. */
  204.     case 'o':
  205.       if (user_output_filename) free (user_output_filename);
  206.       os2_path_sep (user_output_filename = strdup (optarg));
  207.       break;
  208.  
  209.       /* User is specifying that she wishes to dump the subnodes of
  210.          the node that she is dumping. */
  211.     case 's':
  212.       dump_subnodes = 1;
  213.       break;
  214.  
  215.       /* User has specified a string to search all indices for. */
  216.     case APROPOS_OPTION:
  217.       apropos_p = 1;
  218.       maybe_free (apropos_search_string);
  219.       apropos_search_string = strdup (optarg);
  220.       break;
  221.  
  222.       /* User has specified a dribble file to receive keystrokes. */
  223.     case DRIBBLE_OPTION:
  224.       break;
  225.  
  226.       /* User has specified an alternate input stream. */
  227.     case RESTORE_OPTION:
  228.       break;
  229.  
  230.       /* User has specified a string to search all indices for. */
  231.     case IDXSRCH_OPTION:
  232.       index_search_p = 1;
  233.       maybe_free (index_search_string);
  234.       index_search_string = strdup (optarg);
  235.       break;
  236.  
  237.     default:
  238.       usage ();
  239.     }
  240.     }
  241.  
  242.   /* there is no INF file given in the command line -> exit */
  243.   if (!user_filename)
  244.     {
  245.       fprintf (stderr,"\nGnuView, Version %s.\n", gnuview_version_string ());
  246.       fprintf (stderr,"Error: No file to visit.\n");
  247.     }
  248.  
  249.   /* If the user specified --version, then show the version and exit. */
  250.   if (print_version_p)
  251.     {
  252.       printf ("GnuView, Version %s.\n", gnuview_version_string ());
  253.       exit (0);
  254.     }
  255.  
  256.   /* If the `--help' option was present, show the help and exit. */
  257.   if (print_help_p)
  258.     {
  259.       gnuview_short_help ();
  260.       exit (0);
  261.     }
  262.   
  263.   /* If the user hasn't specified a path for INF files, default that path
  264.      now. */
  265.   if (!gnuviewpath)
  266.     {
  267.       char *path_from_env, *getenv ();
  268.  
  269.       path_from_env = getenv ("BOOKSHELF");
  270.  
  271.       if (path_from_env) gnuview_add_path (path_from_env, INFOPATH_PREPEND);
  272.       else               gnuview_add_path (DEFAULT_INFOPATH, INFOPATH_PREPEND);
  273.     }
  274.  
  275.   /* If the user specified a particular filename, add the path of that
  276.      file to the contents of BOOKSHELF. */
  277.   if (user_filename)
  278.     {
  279.       char *directory_name, *temp;
  280.  
  281.       directory_name = strdup (user_filename);
  282.       temp = gnuview_filename_non_directory (directory_name);
  283.  
  284.       if (temp != directory_name)
  285.     {
  286.       *temp = 0;
  287.       gnuview_add_path (directory_name, INFOPATH_PREPEND);
  288.     }
  289.  
  290.       free (directory_name);
  291.     }
  292.  
  293.   gnuview_add_path ("SET BOOKSHELF=", INFOPATH_PREPEND_WITHOUT_COLON);
  294.   gnuview_add_path (" & view ", INFOPATH_APPEND_WITHOUT_COLON);
  295.   gnuview_add_path (user_filename, INFOPATH_APPEND_WITHOUT_COLON);
  296.   gnuview_add_path (" ", INFOPATH_APPEND_WITHOUT_COLON);
  297.  
  298.   if (index_search_string)
  299.     gnuview_add_path (index_search_string, INFOPATH_APPEND_WITHOUT_COLON);
  300.   else if (apropos_search_string)
  301.     gnuview_add_path (apropos_search_string, INFOPATH_APPEND_WITHOUT_COLON);
  302.  
  303.   system (gnuviewpath);
  304.  
  305.   exit (0);
  306. }
  307.  
  308. static void remember_gnuview_program_name (char *fullpath)
  309. {
  310.   char *filename;
  311.   filename = gnuview_filename_non_directory (fullpath);
  312.   program_name = strdup (filename);
  313. }
  314.  
  315. /* Return a string describing the current version of GnuView. */
  316. static char *gnuview_version_string ()
  317. {
  318.   static char *vstring = (char *)NULL;
  319.  
  320.   if (!vstring)
  321.     {
  322.       vstring = (char *)xmalloc (50);
  323.  
  324.       sprintf (vstring, "%d.%d", gnuview_major_version, gnuview_minor_version);
  325.       if (gnuview_patch_level)
  326.         sprintf (vstring + strlen (vstring), "-p%d", gnuview_patch_level);
  327.  
  328.       sprintf (vstring + strlen (vstring), " for OS/2 2.x and Warp");
  329.     }
  330.   return (vstring);
  331. }
  332.  
  333. /* Produce a very brief descripton of the available options and exit with
  334.    an error. */
  335. static void usage ()
  336. {
  337.   fprintf (stderr,"\nGnuView, Version %s.\n", gnuview_version_string ());
  338.   fprintf (stderr,"%s\n%s\n%s\n%s\n%s\n",
  339. "Usage: gnuview -f INF-file [-d dir] [-o outfile-file] [-n node-name]...",
  340. "               [--directory dir] [--file INF-file] [--node node-name]...",
  341. "               [--help] [--output output-file] [--subnodes] [--version]",
  342. "               [--dribble dribble-file] [--restore from-file]",
  343. "               [--index-search string] [menu-selection ...]");
  344.   exit (1);
  345. }
  346.  
  347. /* Produce a scaled down description of the available options to GnuView. */
  348. static void gnuview_short_help ()
  349. {
  350.   printf ("%s", "\
  351. Here is a quick description of GnuView's options.  For a more complete\n\
  352. description of how to use GnuView, type `gnuview gnuview options'.\n\
  353. \n\
  354.    --directory DIR        Add DIR to BOOKSHELF.\n\
  355.    --file FILENAME        Specify INF file to visit.\n\
  356.    --index-search STRING        Specify STRING to search for in the index.\n\
  357.    --node NODENAME        Specify nodes in first visited INF file.\n\
  358.    --output FILENAME        Output selected nodes to FILENAME.\n\
  359.    --dribble FILENAME        Remember user keystrokes in FILENAME.\n\
  360.    --restore FILENAME        Read initial keystrokes from FILENAME.\n\
  361.    --subnodes            Recursively output menu items.\n\
  362.    --help            Get this help message.\n\
  363.    --version            Display GnuView's version information.\n\
  364. \n\
  365. Remaining arguments to GnuView are treated as the names of menu\n\
  366. items in the initial node visited.  You can easily move to the\n\
  367. node of your choice by specifying the menu names which describe\n\
  368. the path to that node.  For example, `gnuview emacs buffers'.\n");
  369.  
  370.   exit (0);
  371. }
  372.  
  373. /* Add PATH to the list of paths found in BOOKSHELF.  2nd argument says
  374.    whether to put PATH at the front or end of BOOKSHELF. */
  375. static void gnuview_add_path (char *path, int where)
  376. {
  377.   int len;
  378.  
  379.   if ((where != INFOPATH_APPEND_WITHOUT_COLON) &&
  380.       (where != INFOPATH_PREPEND_WITHOUT_COLON))
  381.     os2_path_sep (path);
  382.  
  383.   if (!gnuviewpath)
  384.     {
  385.       gnuviewpath = (char *)xmalloc (gnuviewpath_size = 200 + strlen (path));
  386.       gnuviewpath[0] = '\0';
  387.     }
  388.  
  389.   len = strlen (path) + strlen (gnuviewpath);
  390.  
  391.   if (len + 2 >= gnuviewpath_size)
  392.     gnuviewpath = (char *) xrealloc (gnuviewpath,
  393.                      (gnuviewpath_size += (2 * len) + 2));
  394.  
  395.   if (!*gnuviewpath)
  396.     strcpy (gnuviewpath, path);
  397.   else if (where == INFOPATH_APPEND)
  398.     {
  399.       strcat (gnuviewpath, COLONSTR);
  400.       strcat (gnuviewpath, path);
  401.     }
  402.   else if (where == INFOPATH_APPEND_WITHOUT_COLON)
  403.     {
  404.       strcat (gnuviewpath, path);
  405.     }
  406.   else if (where == INFOPATH_PREPEND)
  407.     {
  408.       char *temp = strdup (gnuviewpath);
  409.       strcpy (gnuviewpath, path);
  410.       strcat (gnuviewpath, COLONSTR);
  411.       strcat (gnuviewpath, temp);
  412.       free (temp);
  413.     }
  414.   else if (where == INFOPATH_PREPEND_WITHOUT_COLON)
  415.     {
  416.       char *temp = strdup (gnuviewpath);
  417.       strcpy (gnuviewpath, path);
  418.       strcat (gnuviewpath, temp);
  419.       free (temp);
  420.     }
  421. }
  422.  
  423. /* Return a pointer to the part of PATHNAME that simply defines the file. */
  424. static char *gnuview_filename_non_directory (char *pathname)
  425. {
  426.   char *filename;
  427.  
  428.   os2_path_sep (pathname);
  429.  
  430.   filename = (char *) strrchr (pathname, PATHSEPCHR);
  431.  
  432.   if (filename) filename++;
  433.   else          filename = pathname;
  434.  
  435.   return (filename);
  436. }
  437.  
  438. /* Replace '/' with '\\' in the argument */
  439. static void os2_path_sep (char *filename)
  440. {
  441.   char *c;
  442.  
  443.   c = filename;
  444.  
  445.   while (*c)
  446.     {
  447.       if ((*c) == '/')  (*c) = PATHSEPCHR;
  448.       c++;
  449.     }
  450. }
  451.